﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PostSharp.Aspects;
using System.Reflection;

namespace Aspects
{
    [Serializable]
    public class ValidationAttribute : OnMethodBoundaryAspect
    {
        /// <summary>
        /// 需要跳过验证的参数名
        /// </summary>
        /// <returns></returns>
        public string[] SkipValidationParams { get; set; }

        /// <summary>
        /// 当验证失败时默认的返回值
        /// </summary>
        /// <returns></returns>
        public object DefaultReturnValue { get; set; }

        public override void OnEntry(MethodExecutionArgs args)
        {
            ParameterInfo[] parmas = args.Method.GetParameters();
            bool isValidation = true;
            foreach (ParameterInfo param in parmas)
            {
                if (SkipValidationParams != null && SkipValidationParams.Contains(param.Name))
                    continue;
                if (param.IsOptional == true)
                    continue;
                dynamic value = args.Arguments.GetArgument(param.Position);
                if (param.ParameterType.IsClass == true)
                {
                    if (value == null)
                    {
                        isValidation = false;
                        break;
                    }
                }
                else
                {
                    if (param.ParameterType == typeof(DateTime))
                    {
                        if (Convert.ToDateTime(value) == default(DateTime))
                        {
                            isValidation = false;
                            break;
                        }
                    }
                    InRangeAttribute inRange = null;
                    object[] attrs = param.GetCustomAttributes(typeof(InRangeAttribute), true);
                    if (attrs.Length > 0)
                    {
                        inRange = attrs[0] as InRangeAttribute;
                    }
                    if (inRange != null)
                    {
                        dynamic maxValue = inRange.Max;
                        dynamic minValue = inRange.Min;
                        if (maxValue != null && value > maxValue)
                        {
                            isValidation = false;
                            break;
                        }
                        if (minValue != null && value < minValue)
                        {
                            isValidation = false;
                            break;
                        }
                    }
                }
            }
            if (isValidation == false)
            {
                if (DefaultReturnValue != null)
                {
                    args.ReturnValue = DefaultReturnValue;
                }
                args.FlowBehavior = FlowBehavior.Return;
            }
        }
    }
}
